An essential task for many computer systems is the handling of input/output (I/O). For example, to save data, a computer system typically transfers data from temporary data storage, such as random access memory (RAM), to more permanent data storage, such as a hard drive (e.g., magnetic storage device). From the perspective of the computer system (more specifically a central processing unit (CPU) and main memory of the computer system), such data transfer involves the output of data. As another example, to display a webpage on a computer monitor, a computer system might receive data encoding the webpage from one or more servers (i.e., input from the perspective of the computer system) and might transmit data encoding the webpage to a monitor (i.e., output from the perspective of the computer system).
One component that may oversee the processing of I/O is the CPU of the computer system. Two common techniques used by the CPU to mediate communication with an “external device” (or I/O device) are polling and interrupt-driven I/O. Any device which is external to the CPU and its associated main memory may be referred to as an external device. An external device may include a hard drive, a solid state drive (SSD), a monitor, a keyboard, a microphone, etc.
In polling, a CPU periodically queries an external device to see whether the external device is ready to receive data from the CPU or transmit data to the CPU. While polling is relatively simple to implement, it may be quite inefficient, unnecessarily consuming resources of the CPU while an external device is not ready to handle I/O. In contrast to polling, with interrupt-driven I/O, an external device may send an interrupt to the CPU when it is ready to receive data from the CPU or transmit data from the CPU. Therefore, with interrupts, a CPU only needs to communicate with an external device while it is actively servicing I/O.
However, even the servicing of I/O may consume much of the computing resources of the CPU. In the case of transferring a large file from main memory to a storage device, a CPU may need to oversee the transfer of each data block of the file from the main memory to the storage device, which may take may cycles of the CPU's time. If the large file were a video and the CPU had limited computing power (e.g., lower clock frequency), the storage of the video might consume much of the CPU resources, slowing the CPU's response to other tasks. One solution used to address such predicament is a direct memory access (DMA) controller (also known as a DMA engine). With a DMA controller, the handling of I/O can be assisted by the DMA controller, freeing up the CPU for other tasks.
More specifically, the handling of I/O assisted by a DMA controller may begin with the CPU issuing an I/O request (either to the DMA controller or to the external device). The DMA controller then works with the external device to complete the I/O request (i.e., transferring data from the main memory to the external device or transferring data from the external device to the main memory). Such step may be called a DMA transfer. Upon completion of the I/O request, the DMA controller may send an interrupt to the CPU, alerting the CPU to the completion of the I/O request. A DMA transfer is asynchronous in the sense that the CPU does not have control of when the DMA transfer actually happens.
While a DMA controller provides the above-noted benefits of freeing the CPU for other tasks, it also introduces some challenges when I/O requests need to be cancelled. To illustrate the need for the cancellation of an I/O request, an application may request data from a device (i.e., the I/O request being a read request in this example), but at a later point may need to cancel the I/O request upon realizing that the data is no longer needed. In a not uncommon scenario, an I/O request may take longer to complete than expected, and becoming impatient, a user may attempt to cancel the I/O request.
When a CPU is overseeing an I/O request (without the assistance of a DMA controller), the CPU can make sure that the I/O request is canceled by (i) sending a reset or cancellation message to the external device and (ii) in the event that the external device still provides a response to the I/O request, not writing the response to the main memory. The addition of the DMA controller may introduce some complications. When a CPU is overseeing an I/O request (with the assistance of a DMA controller), the CPU may similarly send a reset or cancellation message to the external device. However, in the event that the external device still provides a response to the I/O request (e.g., the external device fails to handle the cancellation request properly, there is a bug in the implementation of the reset logic of the external device, etc.), the DMA controller may write the response to the main memory. Such action of the DMA may corrupt the main memory of the computer system.